/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package me.panpf.sketch.sample;

import me.panpf.sketch.display.TransitionImageDisplayer;
import me.panpf.sketch.process.GaussianBlurImageProcessor;
import me.panpf.sketch.request.DisplayOptions;
import me.panpf.sketch.request.DownloadOptions;
import me.panpf.sketch.request.LoadOptions;
import me.panpf.sketch.request.ShapeSize;
import me.panpf.sketch.shaper.CircleImageShaper;
import me.panpf.sketch.shaper.RoundRectImageShaper;
import me.panpf.sketch.util.SketchUtils;
import ohos.agp.utils.Color;
import ohos.agp.utils.Point;
import ohos.agp.window.service.Display;
import ohos.agp.window.service.DisplayManager;
import ohos.app.Context;
import ohos.media.image.common.PixelFormat;
import ohos.utils.PlainArray;

import java.util.Optional;

/**
 * ImageOptions
 */
public class ImageOptions {
    /**
    * 通用矩形
    */
    public static final int RECT = 101;

    /**
     * 带描边的圆形
     */
    public static final int CIRCULAR_STROKE = 102;

    /**
     * 窗口背景
     */
    public static final int WINDOW_BACKGROUND = 103;

    /**
     * 圆角矩形
     */
    public static final int ROUND_RECT = 104;

    /**
     * 充满列表
     */
    public static final int LIST_FULL = 105;

    private static final PlainArray<OptionsHolder> OPTIONS_ARRAY = new PlainArray<>();

    public ImageOptions() {
        TransitionImageDisplayer transitionImageDisplayer = new TransitionImageDisplayer();

        OPTIONS_ARRAY.append(ImageOptions.RECT, new OptionsHolder() {
            @Override
            protected DownloadOptions onCreateOptions(Context context) {
                return new DisplayOptions()
                        .setLoadingImage(ResourceTable.Media_image_loading)
                        .setErrorImage(ResourceTable.Media_image_error)
                        .setPauseDownloadImage(ResourceTable.Media_image_pause_download)
                        .setDisplayer(transitionImageDisplayer)
                        .setShapeSize(ShapeSize.byViewFixedSize());
            }
        });

        OPTIONS_ARRAY.append(ImageOptions.CIRCULAR_STROKE, new OptionsHolder() {
            @Override
            protected DownloadOptions onCreateOptions(Context context) {
                return new DisplayOptions()
                        .setLoadingImage(ResourceTable.Media_image_loading)
                        .setErrorImage(ResourceTable.Media_image_error)
                        .setPauseDownloadImage(ResourceTable.Media_image_pause_download)
                        .setDisplayer(transitionImageDisplayer)
                        .setShaper(new CircleImageShaper().setStroke(Color.WHITE.getValue(), SketchUtils.dp2px(context, 1)))
                        .setShapeSize(ShapeSize.byViewFixedSize());
            }
        });

        OPTIONS_ARRAY.append(ImageOptions.WINDOW_BACKGROUND, new OptionsHolder() {
            @Override
            protected DownloadOptions onCreateOptions(Context context) {
                Optional<Display> display = DisplayManager.getInstance().getDefaultDisplay(context);
                Point pt = new Point();
                display.get().getSize(pt);
                return new DisplayOptions()
                        .setProcessor(GaussianBlurImageProcessor.makeLayerColor(Color.getIntColor("#66000000")))
                        .setCacheProcessedImageInDisk(true)
                        .setBitmapConfig(PixelFormat.ARGB_8888)   // 效果比较重要
                        .setShapeSize(ShapeSize.byViewFixedSize())
                        .setMaxSize((int) pt.getPointX() / 4,
                                (int) (pt.getPointY() / 4))
                        .setDisplayer(new TransitionImageDisplayer(true));
            }
        });

        OPTIONS_ARRAY.append(ImageOptions.ROUND_RECT, new OptionsHolder() {
            @Override
            protected DownloadOptions onCreateOptions(Context context) {
                return new DisplayOptions()
                        .setLoadingImage(ResourceTable.Media_image_loading)
                        .setErrorImage(ResourceTable.Media_image_error)
                        .setPauseDownloadImage(ResourceTable.Media_image_pause_download)
                        .setShaper(new RoundRectImageShaper(SketchUtils.dp2px(context, 6)))
                        .setDisplayer(transitionImageDisplayer)
                        .setShapeSize(ShapeSize.byViewFixedSize());
            }
        });

        OPTIONS_ARRAY.append(ImageOptions.LIST_FULL, new OptionsHolder() {
            @Override
            protected DownloadOptions onCreateOptions(Context context) {
                Optional<Display> display = DisplayManager.getInstance().getDefaultDisplay(context);
                Point pt = new Point();
                display.get().getSize(pt);
                return new DisplayOptions()
                        .setLoadingImage(ResourceTable.Media_image_loading)
                        .setErrorImage(ResourceTable.Media_image_error)
                        .setPauseDownloadImage(ResourceTable.Media_image_pause_download)
                        .setMaxSize((int) pt.getPointX(), (int) pt.getPointY())
                        .setDisplayer(transitionImageDisplayer);
            }
        });
    }

    /**
     * getDisplayOptions
     * @param context
     * @param optionsId
     * @return DisplayOptions
     */
    public static DisplayOptions getDisplayOptions(Context context, Type optionsId) {
        Optional<OptionsHolder> options = OPTIONS_ARRAY.get(optionsId.type);
        return options.map(optionsHolder -> ((DisplayOptions) optionsHolder.getOptions(context))).orElse(null);
    }

    /**
     * getLoadOptions
     * @param context
     * @param optionsId
     * @return LoadOptions
     */
    public LoadOptions getLoadOptions(Context context, Type optionsId) {
        Optional<OptionsHolder> options = OPTIONS_ARRAY.get(optionsId.type);
        return options.map(optionsHolder -> ((LoadOptions) optionsHolder.getOptions(context))).orElse(null);
    }

    /**
     * getDownloadOptions
     * @param context
     * @param optionsId
     * @return DownloadOptions
     */
    public DownloadOptions getDownloadOptions(Context context, Type optionsId) {
        Optional<OptionsHolder> options = OPTIONS_ARRAY.get(optionsId.type);
        return options.map(optionsHolder -> (optionsHolder.getOptions(context))).orElse(null);
    }

    private abstract static class OptionsHolder {
        private volatile DownloadOptions options = null;

        private DownloadOptions getOptions(Context context) {
            if (options == null) {
                synchronized(this) {
                    if (options == null) {
                        options = onCreateOptions(context);
                    }
                }
            }
            return options;
        }

        /**
         * onCreateOptions
         * @param context
         * @return DownloadOptions
         */
        protected abstract DownloadOptions onCreateOptions(Context context);
    }

    /**
     * Type
     */
    public enum Type {
        RECT(ImageOptions.RECT),
        CIRCULAR_STROKE(ImageOptions.CIRCULAR_STROKE),
        WINDOW_BACKGROUND(ImageOptions.WINDOW_BACKGROUND),
        ROUND_RECT(ImageOptions.ROUND_RECT),
        LIST_FULL(ImageOptions.LIST_FULL);

        private int type;

        Type(int type) {
            this.type = type;
        }
    }
}
